home *** CD-ROM | disk | FTP | other *** search
/ Computer Select (Limited Edition) / Computer Select.iso / dobbs / v17n02 / inhook.exe / INTHOOK.C < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-07  |  7.0 KB  |  218 lines

  1. /****************************************************************************/
  2. /*                                        */
  3. /*    INTHOOK.C: Sample application to illustrate interrupt hooking under   */
  4. /*         Windows 3.0 using DPMI 0.9 services                */
  5. /*                                        */
  6. /*    Written by Walter Oney                            */
  7. /*    Requires Microsoft C 6.0A                         */
  8. /*                                        */
  9. /****************************************************************************/
  10.  
  11. /* Include files */
  12. #include "windows.h"            /* MS windows dcls */
  13. #include "dos.h"                /* for FP_SEG, FP_OFF */
  14.  
  15. /* Local procedures and data */
  16.      static HANDLE hInst ;    /* current instance handle */
  17.      static HWND hMyWindow ;    /* handle for our window */
  18.      static void (interrupt far *org60)() ; /* original INT 60 handler */
  19.      static void (far *callback)() ; /* real mode callback address */
  20.      typedef struct
  21.     {            /* real mode callback */
  22.     unsigned long edi, esi, ebp, junk, ebx, edx, ecx, eax ;
  23.     unsigned short flags, es, ds, fs, gs, ip, cs, sp, ss ;
  24.     } CBSTRUCT ;        /* real mode callback */
  25.      CBSTRUCT cb60 ;        /* callback for INT 60 handling */
  26.  
  27.      static void hook60(void) ; /* hook INT 60 */
  28.      static void unhook60(void) ; /* unhook INT 60 */
  29.      static void interrupt far int60() ; /* interrupt handler */
  30.  
  31. /**********************************************************************/
  32.  
  33. /* Main window procedure: */
  34.  
  35.      LONG FAR PASCAL MainWndProc
  36.     (HWND hWnd,        /* window handle */
  37.     WORD iMessage,        /* message code */
  38.     WORD wParam,        /* 1st parameter */
  39.     LONG lParam)        /* 2d parameter */
  40.     {            /* MainWndProc */
  41.  
  42. /* Local variables */
  43.     long retcode = 0 ;    /* return code */
  44.  
  45. /* Text */
  46.     switch(iMessage)
  47.        {            /* process message */
  48.  
  49.     case WM_CREATE:
  50.        hMyWindow = hWnd ;    /* so INT60 can find it */
  51.        hook60() ;
  52.        break ;
  53.  
  54.     case WM_USER:        /* posted by int60() */
  55.        MessageBox(GetFocus(), "Wake up!", "Salutations",
  56.           MB_ICONEXCLAMATION | MB_OK) ;
  57.        break ;
  58.  
  59.     case WM_DESTROY:    /* window being destroyed */
  60.        unhook60() ;
  61.        PostQuitMessage(0) ;
  62.        break ;
  63.  
  64.     default:        /* some other message */
  65.        retcode = DefWindowProc(hWnd, iMessage, wParam, lParam) ;
  66.        break ;
  67.        }            /* process message */
  68.     return retcode ;
  69.     }            /* MainWndProc */
  70.  
  71. /**********************************************************************/
  72.  
  73. /* Window message loop: */
  74.  
  75.      int PASCAL WinMain
  76.     (HANDLE hInstance,    /* current instance */
  77.     HANDLE hPrevInstance,    /* previous instance (if any) */
  78.     LPSTR lpCmdLine,    /* command line */
  79.     int nCmdShow)        /* show window type (open/icon) */
  80.     {            /* WinMain */
  81.  
  82. /* Local variables */
  83.     HWND hWnd ;        /* window handle */
  84.     MSG msg ;        /* current message */
  85.     WNDCLASS wc ;        /* template for this class */
  86.  
  87. /* Text */
  88.  
  89. /* Only allow one instance of the application at a time -- there's only
  90.    one interrupt vector to hook! */
  91.     if (hPrevInstance)
  92.        return FALSE ;
  93.  
  94. /* Create the window class. */
  95.     wc.style = 0 ;        /* default styles */
  96.     wc.lpfnWndProc = MainWndProc ; /* window proc */
  97.     wc.cbClsExtra = 0 ;    /* no extra bytes for class */
  98.     wc.cbWndExtra = 0 ;    /* no extra bytes for instance */
  99.     wc.hInstance = hInstance ; /* who created the class */
  100.     wc.hIcon = LoadIcon(NULL, IDI_APPLICATION) ;
  101.     wc.hCursor = LoadCursor(NULL, IDC_ARROW) ; /* default cursor */
  102.     wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH) ;
  103.     wc.lpszMenuName = NULL ; /* no menu */
  104.     wc.lpszClassName = "AppWClass" ; /* name of window class */
  105.     if (!RegisterClass(&wc))
  106.        return FALSE ;
  107.  
  108. /* Create an instance of the class (i.e., our own window) */
  109.     hInst = hInstance ;    /* so window proc can access it */
  110.     hWnd = CreateWindow("AppWClass",
  111.        "Interrupt Hook Sample Application",
  112.        WS_OVERLAPPEDWINDOW,
  113.        CW_USEDEFAULT,
  114.        CW_USEDEFAULT,
  115.        CW_USEDEFAULT,
  116.        CW_USEDEFAULT,
  117.        NULL, NULL, hInstance, NULL) ;
  118.     if (!hWnd)
  119.        return FALSE ;
  120.     ShowWindow(hWnd, SW_SHOWMINIMIZED) ;
  121.     UpdateWindow(hWnd) ;
  122.  
  123. /* Main message loop */
  124.     while (GetMessage(&msg, NULL, NULL, NULL))
  125.        {             /* until WM_QUIT message */
  126.        TranslateMessage(&msg) ; /* xlate virtual key codes */
  127.        DispatchMessage(&msg) ; /* dispatch handler */
  128.        }             /* until WM_QUIT message */
  129.     return msg.wParam ;    /* PostQuitMessage's arg */
  130.     }            /* WinMain */
  131.  
  132. /**********************************************************************/
  133.  
  134. /* HOOK60 hooks software interrupt 60h in real mode, using a real-mode
  135.    callback to get control passed to int60(). */
  136.  
  137.      static void hook60()
  138.     {            /* hook60 */
  139.     _asm
  140.        {
  141.        push  ds        ; save DS across call
  142.  
  143.        mov     ax, ds     ; ES:DI -> callback structure
  144.        mov     es, ax     ;   ..
  145.        mov     di, offset cb60;   ..
  146.        mov     ax, cs     ; DS:SI -> routine to call
  147.        mov     ds, ax     ;   ..
  148.        mov     si, offset int60 ; ..
  149.        mov     ax, 0303h    ; fcn 0303: allocate real mode callback
  150.        int     31h        ; issue DPMI function request
  151.  
  152.        pop     ds        ; restore DS
  153.        mov     callback, dx    ; CX:DX = callback address
  154.        mov     callback+2, cx ;   ..
  155.  
  156.        mov     bl, 60h    ; BL = interrupt number (60h)
  157.        mov     ax, 0200h    ; fcn 0200: get real mode interrupt vector
  158.        int     31h        ; issue DPMI function request
  159.        mov     org60, dx    ; CX:DX = original real mode vector
  160.        mov     org60+2, cx    ;   ..
  161.  
  162.        mov     dx, callback    ; CX:DX = new REAL MODE handler address
  163.        mov     cx, callback+2 ;   ..
  164.        mov     ax, 0201h    ; fcn 0201: set real mode interrupt vector
  165.        int     31h        ; issue DPMI fcn request
  166.        }
  167.     }            /* hook60 */
  168.  
  169. /**********************************************************************/
  170.  
  171. /* UNHOOK60 restores the original interrupt 60h vector. */
  172.  
  173.      static void unhook60()
  174.     {            /* unhook60 */
  175.     _asm
  176.        {
  177.        mov     dx, org60    ; CX:DX = original INT 60 vector
  178.        mov     cx, org60+2    ;   ..
  179.        mov     bl, 60h    ; BL = interrupt number (60h)
  180.        mov     ax, 0201h    ; fcn 0201: set real mode interrupt vector
  181.        int     31h        ; issue DPMI fcn request
  182.  
  183.        mov     dx, callback    ; CX:DX = real-mode callback address
  184.        mov     cx, callback+2 ;   ..
  185.        mov     ax, 0304h    ; fcn 0304: free real mode callback
  186.        int     31h        ; issue DPMI fcn request
  187.        }
  188.     }            /* unhook60 */
  189.  
  190. /**********************************************************************/
  191.  
  192. /* INT60 is the interrupt handler for interrupt 60h. It gains control from
  193.    the real-mode callback address allocated by HOOK60() and uses PostMessage
  194.    to send a message to the application's window procedure. */
  195.  
  196.      typedef struct
  197.     {            /* interrupt register structure */
  198.     unsigned short es, ds ;
  199.     unsigned short di, si, bp, sp, bx, dx, cx, ax ;
  200.     unsigned short flags, ip, cs ;
  201.     } IFRAME ;        /* interrupt register structure */
  202.  
  203.      static void interrupt far int60(IFRAME f)
  204.     {            /* int60 */
  205.     unsigned int far *isp ; /* interrupting stack pointer */
  206.  
  207. /* Simulate IRET in signalling process. */
  208.     FP_SEG(isp) = f.ds ;
  209.     FP_OFF(isp) = f.si ;
  210.     cb60.ip = isp[0] ;
  211.     cb60.cs = isp[1] ;
  212.     cb60.flags = isp[2] ;
  213.     cb60.sp += 6 ;
  214.  
  215. /* Post a private message leading to a message box. */
  216.     PostMessage(hMyWindow, WM_USER, NULL, NULL) ;
  217.     }            /* int60 */
  218.